#include "probset.h"
#include "rand.h"
#include <stdio.h>
//#include "util/mmgr.h"		    // Needs to come in early

#include <cassert>

using namespace num;

ProbSet::ProbSet(unsigned int	Entries) : 
	m_Total(0.0f),
	m_Entries(Entries),
	m_SetA(0)
{
	Init((int)Entries);
	SetRandom(&num::RAND32::Instance());	// default
}

void	ProbSet::Init(int Entries)
{
	if (m_SetA)
	{
		delete [] m_SetA;
	}
	m_Entries = (unsigned int)Entries;
	m_SetA = new float[m_Entries];
	for (unsigned int i=0; i<m_Entries; i++)
	{
		m_SetA[i] = 0.0f;
	}
}

ProbSet::~ProbSet()
{
	delete [] m_SetA;
	m_SetA = NULL;
}

ProbSet*	ProbSet::Clone()
{
	ProbSet* pSet = new ProbSet(m_Entries);
	for (unsigned int i=0; i<m_Entries; i++)
	{
		pSet->m_SetA[i] = m_SetA[i];
	}
	pSet->RecalcSet();
	pSet->SetRandom(m_pRand);
	return pSet;
}

void	ProbSet::FromSet(ProbSet& Set)
{
	Init((int)Set.m_Entries);
	for (int i=0; i<(int)Set.m_Entries; i++)
	{
		m_SetA[i] = Set.m_SetA[i];
	}
	RecalcSet();
}

void	ProbSet::SetProbability(unsigned int Entry, float Probability)
{
	if (Probability < 0) Probability = 0;	// stupid designers...
	if (m_SetA && Entry < m_Entries)
	{
		m_SetA[Entry] = Probability;
	}
	RecalcSet();
}

float	ProbSet::GetProbability(unsigned int Entry)
{
	if (m_SetA && Entry < m_Entries)
	{
		return m_SetA[Entry];
	}
	return 0.0f;
}

void	ProbSet::RecalcSet()
{
	m_Total = 0.0f;
	for (unsigned int i=0; i<m_Entries; i++)
	{
		m_Total += m_SetA[i];
	}
}

unsigned int	ProbSet::GetWeightedEntry()
{
	if (!m_SetA) return 0;

	assert(m_pRand);
	float	Res = m_pRand->RandFloat(0, m_Total);
	for (unsigned int i=0; i<m_Entries; i++)
	{
		Res -= m_SetA[i];
		if (Res <= 0.0f) return i;
	}
	return m_Entries-1;
}
